package com.nio.c5_网络编程.selector.readServer;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.util.Iterator;

/**
 * @version No one is coming, unless you change yourself!!!
 * @author： pang-yun
 * @date： 2021-06-01 10:36
 */

/*
* 读取时断开引起的两个异常
* - 正常断开时   read 返回-1
* - 异常断开时  需要抓住异常  否则会出现空指针
* */

public class ReadSelectorServer {
    public static void main(String[] args) throws IOException {
        Selector selector = Selector.open();

        ServerSocketChannel ssc = ServerSocketChannel.open();
        ssc.configureBlocking(false);

        SelectionKey sscKey = ssc.register(selector, 0, null);
        sscKey.interestOps(SelectionKey.OP_ACCEPT);

        ssc.bind(new InetSocketAddress(8080));

        while (true) {
            selector.select();

            Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
            while (iterator.hasNext()) {
                SelectionKey key = iterator.next();
                //==================================非常重要，一定要从selectedKeys中删除，否则下次处理就会出问题
                iterator.remove();
                //=================================

                //看key是什么类型，区分之后开始处理
                if (key.isAcceptable()) { //是请求类型时
                    ServerSocketChannel channel = (ServerSocketChannel) key.channel();
                    SocketChannel sc = channel.accept();

                    sc.configureBlocking(false); //将连接设置为非阻塞
                    SelectionKey scKey = sc.register(selector, 0, null);// 将SocketChannel注册到 selector中
                    scKey.interestOps(SelectionKey.OP_READ);


                } else if (key.isReadable()) { //如果只是read
                    try {
                        SocketChannel channel = (SocketChannel) key.channel(); //拿到读取事件的channel
                        ByteBuffer byteBuffer = ByteBuffer.allocate(16);
                        int read = channel.read(byteBuffer);   //如果是正常断开  read返回的方法是-1
                        if (read == -1) {
                            key.cancel();
                        } else {
                            byteBuffer.flip();
                            while (byteBuffer.hasRemaining()) {
                                byte b = byteBuffer.get();
                                System.out.println((char) b);
                            }
                        }

                    } catch (IOException e) {
                        e.printStackTrace();
                        key.cancel();   //客户端断开了，因此需要将key取消（从selector的keys集合中真正删除key）
                    }


                }

            }


        }

    }
}
